﻿using System;
using System.Runtime.InteropServices;
using System.Text;
using static Avalonia.Extensions.Base.Win32API;

namespace Avalonia.BiliBili.Libs.Message
{
    public sealed class Windows
    {
        private static Windows instance;
        public static Windows Instance
        {
            get
            {
                instance ??= new Windows();
                return instance;
            }
        }
        private IntPtr hwnd;
        private WndProc _wndProcDelegate;
        private readonly string lpClassName;
        const int WM_COPYDATA = 0x004A;
        private IntPtr _instance = IntPtr.Zero;
        private Windows()
        {
            lpClassName = $"BilibiliMessageWindow{Guid.NewGuid():N}";
        }
        public void Initialize()
        {
            if (_instance != IntPtr.Zero)
            {
                _instance = GetModuleHandle(null);
                _wndProcDelegate = new WndProc(WndProc);
                WNDCLASSEX wndClassEx = new WNDCLASSEX
                {
                    hInstance = _instance,
                    lpszClassName = lpClassName,
                    cbSize = Marshal.SizeOf<WNDCLASSEX>(),
                    lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate)
                };
                ushort atom = RegisterClassEx(ref wndClassEx);
                if (atom != 0)
                    hwnd = CreateWindowEx(0, atom, null, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            }
        }
        public void Dispose()
        {
            if (_instance != IntPtr.Zero)
            {
                DestroyWindow(hwnd);
                UnregisterClass(lpClassName, _instance);
            }
        }
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(int hWnd, int msg, int wParam, ref COPYDATASTRUCT lParam);
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool DestroyWindow(IntPtr hwnd);
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern bool UnregisterClass(string lpClassName, IntPtr hInstance);
        public void Send(string lpClassName, string dataJson)
        {
            try
            {
                int hWnd = FindWindow(lpClassName, null);
                var cds = new COPYDATASTRUCT
                {
                    dwData = 0,
                    lpData = dataJson,
                    cbData = Encoding.Default.GetBytes(dataJson).Length + 1
                };
                SendMessage(hWnd, WM_COPYDATA, 0, ref cds);
            }
            catch { }
        }
        public struct COPYDATASTRUCT
        {
            /// <summary>
            /// 若发送较小数据可用此字段传输
            /// </summary>
            public int dwData;
            /// <summary>
            /// 发送数据的大小（以字节为单位）
            /// </summary>
            public int cbData;
            /// <summary>
            /// 发送数据
            /// </summary>
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }
        private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            Enum.TryParse(typeof(WindowsMessage), msg.ToString(), out object msgId);
            switch ((WindowsMessage)msgId)
            {
                case WindowsMessage.WM_PLAY:
                    break;
                case WindowsMessage.WM_SEEK:
                    break;
                case WindowsMessage.WM_STOP:
                    break;
                case WindowsMessage.WM_PAUSE:
                    break;
                case WindowsMessage.WM_END:
                    break;
                case WindowsMessage.WM_FULL:
                    break;
                case WindowsMessage.WM_NORMAL:
                    break;
            }
            return DefWindowProc(hWnd, msg, wParam, lParam);
        }
    }
}